/*
****************************************************************************************************************
*= = 版权信息：Copyright (C) 356 - 999. Ombres Industry Empiral. All rights reserved.
*= = 文件名称：Orcinus.h
*= = 功能描述：工业系统电力协议声明主文件
*= = 编写人员：Carlyon W. Tung
****************************************************************************************************************
*/


#ifndef __ORCINUS_H__
#define __ORCINUS_H__

#ifdef  __cplusplus
extern "C" {
#endif // End of __cplusplus


/*
*===============================================================================================================
*= = 声明文件
*===============================================================================================================
*/

#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <math.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#ifdef __INSIGHT_OS_WINDOWS__
#include <io.h>
#include <process.h>
#include <Windows.h>
#else
#include <dirent.h>
#include <sys/time.h>
#include <unistd.h>
#endif // End of __INSIGHT_OS_WINDOWS__

#include "Hollow.h"

#ifdef __INSIGHT_OS_LINUX__
#include <syslog.h>
#endif

#ifdef __ORCINUS_AS_SERVICE__
#include "Spirit.h"
#endif

/*
*===============================================================================================================
*= = 宏定义
*===============================================================================================================
*/

#ifdef __INSIGHT_OS_WINDOWS__
    #ifndef INET_ADDRSTRLEN
        #define INET_ADDRSTRLEN     16
    #endif

    #ifndef INET6_ADDRSTRLEN
        #define INET6_ADDRSTRLEN    46
    #endif
#endif

#define IEC_MAX_SECTORS     10240
#define IEC_MAX_SOCKETS     4096
#define IEC_MAX_IOA         0xffffff

/* IEC object flags */
#define IECF_O_NO_TIME      0x01        /* Data used without timestamp */
#define IECF_O_NO_SPONT     0x02        /* Do not transmit on value change */
#define IECF_O_SUBSTITUTED  0x04        /* Manual input */

/* IEC socket flags */
#define IECF_S_IPV6         0x01        /* Protocol version: IPV4/6 */
#define IECF_S_IC_REQ       0x02        /* C_IC_NA_1 required (otherwise STARTDT only) */
#ifdef __HAVE_SSL_SUPPORT__
#define IECF_S_SSL          0x04        /* Use SSL */
#endif
#define IECF_S_MASTER       0x10        /* IEC master mode */
#define IECF_S_SLAVE        0x20        /* IEC slave mode */
#define IECF_S_CLIENT       0x40        /* Client socket */
#define IECF_S_SERVER       0x80        /* Server socket */

/* IEC quality descriptor flags (bitwise OR with new QDS value) */
#define IECF_QDS_COPY       0x0000      /* Set QDS to argument (default) */
#define IECF_QDS_SET        0x0100      /* Set QDS bits corresponding the argument (bitwise OR) */
#define IECF_QDS_RESET      0x0200      /* Clear QDS bits corresponding the argument (bitwise AND NOT) */

/* IEC value types */
#define IECT_SINGLE         0x01        /* Single point value */
#define IECT_DOUBLE         0x02        /* Double point value */
#define IECT_STEP           0x03        /* Step position information */
#define IECT_BITSTRING      0x04        /* Bitstring of 32 bit */
#define IECT_NORMALIZED     0x05        /* Measured value, normalized value */
#define IECT_SCALED         0x06        /* Measured value, scaled value */
#define IECT_FLOAT          0x07        /* Measured value, short floating point value */
#define IECT_INTEGRATED     0x08        /* Integrated total */
#define IECT_MAX            0x08

/* IEC command types */
#define IECC_SINGLE         (IECT_SINGLE | 0x80)
#define IECC_DOUBLE         (IECT_DOUBLE | 0x80)
#define IECC_STEP           (IECT_STEP | 0x80)
#define IECC_NORMALIZED     (IECT_NORMALIZED | 0x80)
#define IECC_SCALED         (IECT_SCALED | 0x80)
#define IECC_FLOAT          (IECT_FLOAT | 0x80)
#define IECC_BITSTRING      (IECT_BITSTRING | 0x80)

/* Regulating step commands */
#define IECF_RCS_DEC        1           /* Step decrement */
#define IECF_RCS_INC        2           /* Step increment */

/* IEC sector status flags */
#define IECF_SECTOR_IN      1
#define IECF_SECTOR_OUT     2
#define IECF_SECTOR_ERROR   4

/*
 * IEC104 constants description
 *
 * Master to slave:
 *
 * T0 (sec): Network connection establishment timeout
 * Timeout for the establishment of the connection with the server.
 * T1 (sec): Response timeout
 * This parameter defines the time in seconds that client waits maximum
 * for an acknowledge from the server
 * T2 (sec): A S-format frame ( ACKRSN ) will be sent at the latest after
 * this time starting from the last received telegram from the server
 * T3 (sec): An U-format frame ( TESTFR ) will be sent at the latest after
 * this time starting from the last received telegram from the server
 * K: Maximum difference between the received sequence number (RSN)
 * and the last acknowledged RSN. The transmitter stops the transmission at K
 * unacknowledged I frames.
 * W: This parameter indicates the number of received I frames after the RSN
 * will be acknowledged at latest from client with a S frame (ACKRSN).
 *
 * Slave to master:
 *
 * T0 (sec): Only important for the client !
 * T1 (sec): This parameter defines the maximum time in seconds that the
 * program should wait for an acknowledge from the client
 * T2 (sec): A S-format frame ( ACKRSN ) will be sent at the latest after
 * this time starting from the last received telegram from the client
 * T3 (sec): An U-format frame ( TESTFR ) will be sent at the latest after
 * this time starting from the last received telegram from the client
 * K: Maximum difference between the received sequence number (RSN)
 * and the last acknowledged RSN.
 * W: The parameter indicates the number of received I-format frames after
 * which the RSN should be acknowledged at the latest from server with
 * a S-format frame (ACKRSN).
 */

/* Disable closing connection if number of unacknowledged frames exceeded const K,
  * possible has the matter on the fast Ehernet sockets */

/* IEC constants */
#define CONST_K             12
#define CONST_W             8
#define CONST_T0            30
#define CONST_T1            15
#define CONST_T2            10
#define CONST_T3            20

#define CONST_CA_LEN        2       /* Length of common address of ASDU field: 1, 2 */
#define CONST_IOA_LEN       3       /* Length of information object address field: 1, 2, 3 */

/* IEC timeouts */
#define IEC_TIMEOUT_IC      3600    /* Interrogation command timeout, s; if zero never send */
#define IEC_TIMEOUT_NT      300     /* Set NON_TOPIC flag timeout, s */
#define IEC_TIMEOUT_CONNECT 10      /* Client reconnect timeout, s */
#define IEC_TIMEOUT_TIMER   1000    /* General timer timeout, ms */

#define IEC_PORT            2404

/* U-Frame functions */
#define STARTDT_ACT         0x04
#define STARTDT_CON         0x08
#define STOPDT_ACT          0x10
#define STOPDT_CON          0x20
#define TESTFR_ACT          0x40
#define TESTFR_CON          0x80

/* IEC error codes */
#define EI_TOOBIG           -1
#define EI_LIMIT            -2
#define EI_SOCKET           -3
#define EI_SECTOR           -4
#define EI_IOA              -5
#define EI_TYPE             -6
#define EI_SOCKETEXIST      -7
#define EI_SECTOREXIST      -8
#define EI_IOAEXIST         -9
#define EI_MASTEREXIST      -10
#define EI_SYNTAX           -11
#define EI_OPTIONS          -12

/* Cause of transmission (standard) */
#define IEC_CT_PER      1       /* periodic, cyclic */
#define IEC_CT_BGSCAN   2       /* background scan */
#define IEC_CT_SPONT    3       /* spontaneous */
#define IEC_CT_INIT     4       /* initialized */
#define IEC_CT_REQ      5       /* request or requested */
#define IEC_CT_ACT      6       /* activation */
#define IEC_CT_ACTCON   7       /* activation confirmation */
#define IEC_CT_DEACT    8       /* deactivation */
#define IEC_CT_DEACTCON 9       /* deactivation confirmation */
#define IEC_CT_ACTTERM  10      /* activation termination */
#define IEC_CT_RETREM   11      /* return information caused by a remote command */
#define IEC_CT_RETLOC   12      /* return information caused by a local command */
#define IEC_CT_FILE     13      /* file transfer */
                                /* 14..19: reserved for further compatible definitions */
#define IEC_CT_INTROGEN 20      /* 20 interrogated by general interrogation */
                                /* 20 + N, N=[1..16]: interrogated by group <N> interrogation */
#define IEC_CT_REQCOGEN 37      /* requested by general counter request reqcogen */
                                /* 37 + N, N=[1..4]: requested by group <N> counter request */
                                /* 42..43: reserved for further compatible definitions */
#define IEC_CT_UK_TYPE  44      /* Unknown ASDU type */
#define IEC_CT_UK_CAUSE 45      /* Unknown cause of transmission */
#define IEC_CT_UK_CA    46      /* Unknown common address of ASDU */
#define IEC_CT_UK_IOA   47      /* Unknown IOA */

/* ASDU types */
#define M_SP_NA_1       1       /* Single point information */ /* SQ=0,1 */
#define M_DP_NA_1       3       /* Double point information */
#define M_ST_NA_1       5       /* Step position information */
#define M_BO_NA_1       7       /* Bitstring of 32 bit */ /* SQ=0 */
#define M_ME_NA_1       9       /* Measured value, normalized value */ /* SQ=0,1 */
#define M_ME_NB_1       11      /* Measured value, scaled value */ /* SQ=0,1 */
#define M_ME_NC_1       13      /* Measured value, short floating point number */ /* S=0 */
#define M_IT_NA_1       15      /* Integrated total */
#define M_PS_NA_1       20      /* ---Packed single point information with status change detection */
#define M_ME_ND_1       21      /* Measured value, normalized value without quality descriptor */ /* SQ=0,1 */
#define M_SP_TB_1       30      /* Single point information with time tag CP56Time2a */ /* SQ=0 */
#define M_DP_TB_1       31      /* Double point information with time tag CP56Time2a */
#define M_ST_TB_1       32      /* Step position information with time tag CP56Time2a */
#define M_BO_TB_1       33      /* Bitstring of 32 bit with time tag CP56Time2a */ /* SQ=0 */
#define M_ME_TD_1       34      /* Measured value, normalized value with time tag CP56Time2a */ /* SQ=0 */
#define M_ME_TE_1       35      /* Measured value, scaled value with time tag CP56Time2a */ /* SQ=0 */
#define M_ME_TF_1       36      /* Measured value, short floating point number with time tag CP56Time2a */ /* S=0 */
#define M_IT_TB_1       37      /* Integrated total with time tag CP56Time2a */

#define M_EP_TD_1       38      /* ---Event of protection equipment with time tag CP56Time2a */
#define M_EP_TE_1       39      /* ---Packed start events of protection equipment with time tag CP56Time2a */
#define M_EP_TF_1       40      /* ---Packed output circuit information of protection equipment with time tag CP56Time2a */

#define C_SC_NA_1       45      /* Single command */
#define C_DC_NA_1       46      /* Double command */
#define C_RC_NA_1       47      /* Regulating step command */
#define C_SE_NA_1       48      /* Set-point command, normalized value */
#define C_SE_NB_1       49      /* Set-point command, scaled value */
#define C_SE_NC_1       50      /* Set-point command, short floating point number */
#define C_BO_NA_1       51      /* Bitstring of 32 bit command */

#define C_SC_TA_1       58      /* Single command with time tag CP56Time2a */
#define C_DC_TA_1       59      /* Double command with time tag CP56Time2a */
#define C_RC_TA_1       60      /* Regulating step command with time tag CP56Time2a */
#define C_SE_TA_1       61      /* Measured value, normalized value command with time tag CP56Time2a */
#define C_SE_TB_1       62      /* Measured value, scaled value command with time tag CP56Time2a */
#define C_SE_TC_1       63      /* Measured value, short floating point number command with time tag CP56Time2a */
#define C_BO_TA_1       64      /* Bitstring of 32 bit command with time tag CP56Time2a */

#define M_EI_NA_1       70      /* ---End of initialization */

#define C_IC_NA_1       100     /* Interrogation command */
#define C_CI_NA_1       101     /* Counter interrogation command */
#define C_RD_NA_1       102     /* Read command */
#define C_CS_NA_1       103     /* Clock synchronisation command */
#define C_TS_NA_1       104     /* Test command */
#define C_RP_NA_1       105     /* Reset process command */
#define C_TS_TA_1       107     /* Test command with time tag CP56Time2a */

#define P_ME_NA_1       110     /* ---Parameter of measured values, normalized value */
#define P_ME_NB_1       111     /* ---Parameter of measured values, scaled value */
#define P_ME_NC_1       112     /* ---Parameter of measured values, short floating point number */
#define P_AC_NA_1       113     /* ---Parameter activation */

#define F_FR_NA_1       120     /* ---File ready */
#define F_SR_NA_1       121     /* ---Section ready */
#define F_SC_NA_1       122     /* ---Call directory, select file, call file, call section */
#define F_LS_NA_1       123     /* ---Last section, last segment */
#define F_AF_NA_1       124     /* ---ACK file, ACK section */
#define F_SG_NA_1       125     /* ---Segment */
#define F_DR_TA_1       126     /* ---Directory */

/* Quality flags */
#define IECF_SPI        0x01    /* single point information */
#define IECF_DPI        0x03    /* double point information */
#define IECF_STEP       0x3F    /* step value */
#define IECF_GN         0x04    /* general */
#define IECF_IN         0x08    /* inversion */
#define IECF_BL         0x10    /* blocked */
#define IECF_SB         0x20    /* substituted */
#define IECF_NT         0x40    /* not topical */
#define IECF_IV         0x80    /* invalid */
#define IECF_OV         0x01    /* overflow */
#define IECF_AV         0x04    /* average */
#define IECF_CP         0x06    /* comma position */
#define IECF_CY         0x20    /* carry (integrated total) */
#define IECF_CA         0x40    /* adjusted (integrated total) */
#define IECF_SQN        0x1F    /* sequence notation (integrated total) */
#define IECF_KPA        0x3F    /* kind of parameter */
#define IECF_POP        0x40    /* parameter in operation */
#define IECF_LPC        0x80    /* local parameter change */
#define IECF_SCS        0x01    /* single command state */
#define IECF_DCS        0x03    /* double command state */
#define IECF_RCS        0x03    /* regulating step command */
#define IECF_QU         0x7C    /* qualifier of command */
#define IECF_SE         0x80    /* select/execute state */
#define IECF_QL         0x7F    /* qualifier of set-point command */
#define IECF_RQT        0x3F    /* request qualifier of counter interrogation command */
#define IECF_FRZ        0xC0    /* freeze/reset qualifier of counter interrogation command */

#define IECF_SU         0x80    /* cp56time2a summer time */
#define IECF_MIN        0x3F    /* cp56time2a minutes */
#define IECF_HOUR       0x1F    /* cp56time2a hours */
#define IECF_DOW        0xE0    /* cp56time2a day of week */
#define IECF_MDAY       0x1F    /* cp56time2a day of month */
#define IECF_MONTH      0x0F    /* cp56time2a month */
#define IECF_YEAR       0x7F    /* cp56time2a year */

#define IECF_RSC_INC    0x02    /* regulating step increment command */
#define IECF_RSC_DEC    0x01    /* regulating step decrement command */

#define IECF_NUM        0x7F    /* number of information objects */
#define IECF_SQ         0x80    /* sequence of information objects */
#define IECF_CAUSE      0x3F    /* cause of transmission */
#define IECF_T          0x40    /* test */
#define IECF_PN         0x80    /* positive/negative confirmation/activation */

#define IEC_GET_CP(arg)         ((arg & IECF_CP) >> 1)
#define IEC_SET_CP(arg, v)      arg |= (v << 1) & IECF_CP
#define IEC_GET_QU(arg)         ((arg & IECF_QU) >> 2)
#define IEC_SET_QU(arg, v)      arg |= (v << 2) & IECF_QU
#define IEC_GET_FRZ(arg)        ((arg & IECF_FRZ) >> 6)
#define IEC_SET_FRZ(arg, v)     arg |= (v << 6) & IECF_FRZ
#define IEC_GET_DOW(arg)        (((arg & IECF_DOW) >> 5) - 1)
#define IEC_SET_DOW(arg, v)     arg |= ((v + 1) << 5) & IECF_DOW
#define IEC_GET_SU(arg)         ((arg & IECF_SU) >> 7)
#define IEC_SET_SU(arg, v)      arg |= (v << 7) & IECF_SU
#define IEC_GET_SQ(arg)         ((arg & IECF_SQ) >> 7)
#define IEC_SET_SQ(arg, v)      arg |= (v << 7) & IECF_SQ
#define IEC_GET_T(arg)          ((arg & IECF_T) >> 6)
#define IEC_SET_T(arg, v)       arg |= (v << 6) & IECF_T
#define IEC_GET_PN(arg)         ((arg & IECF_PN) >> 7)
#define IEC_SET_PN(arg, v)      arg |= (v << 7) & IECF_PN
#define IEC_GET_CAUSE(arg)      (arg & IECF_CAUSE)
#define IEC_SET_CAUSE(arg, v)   arg |= (arg & ~IECF_CAUSE) | v

/*
*===============================================================================================================
*= = 结构体定义
*===============================================================================================================
*/

#pragma pack(push, 1)

/* CP56Time2a timestamp */
typedef struct {
    uint16_t    msec;   // 0..59999ms = 60sec = 1min
    uint8_t     iv_min; // IV|0|MIN(6) 0..59 invalid time, minutes
    uint8_t     su_hour;// SU|0(2)|HOUR(5) hour 0..23
    uint8_t     wd_md;  // WD(3)|MD(5) week day = 1..7, month day = 1..31
    uint8_t     month;  // 0|0|0|0|MON(4) month 1..12
    uint8_t     year;   // 0|YEAR(7) year 0..99
} cp56time2a;

/* Single-point */

/* M_SP_NA_1 - Single-point information */
typedef struct {
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|IN|GN|0|SPI
} asdu1;

/* M_SP_TB_1 - Single-point information with time tag CP56Time2a */
typedef struct {
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|IN|GN|0|SPI
    cp56time2a	time;
} asdu30;

/* M_BO_NA_1 - Bitstring of 32 bit */
typedef struct {
    uint32_t    stcd;
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|IN|GN|0|OV
} asdu7;

/* M_BO_TB_1 - Bitstring of 32 bit with time tag CP56Time2a */
typedef struct {
    uint32_t    stcd;
    uint8_t     qds;     // quality descriptor IV|NT|SB|BL|IN|GN|0|OV
    cp56time2a	time;
} asdu33;

/* Double-point */

/* M_DP_NA_1 - Double-point information */
typedef struct {
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|IN|GN|DPI(2)
} asdu3;

/* M_DP_TB_1 - Double-point information with time tag CP56Time2a */
typedef struct {
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|IN|GN|DPI(2)
    cp56time2a	time;
} asdu31;

/* Measured */

/* M_ME_NA_1 - Measured value, normalized value */
typedef struct {
    int16_t     mv;     // normalized value
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|AV|0|0|OV
} asdu9;

/* M_ME_TD_1 - Measured value, normalized value with time tag CP56Time2a */
typedef struct {
    int16_t     mv;     // normalized value
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|AV|0|0|OV
    cp56time2a	time;
} asdu34;

/* M_ME_NB_1 - Measured value, scaled value */
typedef struct {
    int16_t     mv;     // scaled value
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|AV|CP(2)|OV
} asdu11;

/* M_ME_TE_1 - Measured value, scaled value with time tag CP56Time2a */
typedef struct {
    int16_t     mv;     // scaled value
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|AV|CP(2)|OV
    cp56time2a	time;
} asdu35;

/* M_ME_NC_1 - Measured value, short floating point number */
typedef struct {
    float       mv;     // floating point value
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|AV|0|0|OV
} asdu13;

/* M_ME_TF_1 - Measured value, short floating point number with time tag CP56Time2a */
typedef struct {
    float       mv;     // floating point value
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|AV|0|0|OV
    cp56time2a	time;
} asdu36;

/* M_ME_ND_1 - Normalized value without quality descriptor */
typedef struct {
    int16_t     mv;     // normalized value
} asdu21;

/** NEW **/

/* 137 - NEW - Single floating point values sequence without quality descriptor */
typedef struct {
    float       mv;     // 8-bit value
} asdu137;

/* 138 - NEW - Single floating point values sequence without quality descriptor, with time tag CP56Time2a at the end of block */
typedef struct {
    float       mv;     // 8-bit value
} asdu138;

/* 139 - NEW - Normalized values sequence (1 byte) without quality descriptor */
typedef struct {
    int8_t      mv;     // normalized value
} asdu139;

/* 143 - NEW - Normalized values sequence, with time tag CP56Time2a at the end of block */
typedef struct {
    int16_t     mv;     // normalized value
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|AV|0|0|OV
} asdu143;

/* 144 - NEW - Scaled values sequence, with time tag CP56Time2a at the end of block */
typedef struct {
    int16_t     mv;     // scaled value
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|AV|CP(2)|OV
} asdu144;

/* 145 - NEW - Single floating point values sequence, with time tag CP56Time2a at the end of block */
typedef struct {
    float       mv;     // floating point value
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|AV|0|0|OV
} asdu145;

/* 140 - NEW - Scaled values sequence without quality descriptor, with time tag CP56Time2a at the end of block */
typedef struct {
    int16_t     mv;         /* scaled value */
} asdu140;
/* 141 - NEW - Normalized values (1 byte) sequence without quality descriptor, with time tag CP56Time2a at the end ob block */
typedef struct {
    int8_t      mv;         /* normalized value */
} asdu141;
/* 142 - NEW - Single floating point values sequence without quality descriptor, with time tag CP56Time2a at the end of block */
typedef struct {
    float       mv;         /* floating point value */
} asdu142;

/* Commands */

/* C_SC_NA_1 - Single command */
typedef struct {
    uint8_t     sco;        // Single command SE|QU(5)|0|SCS
} asdu45;

/* C_DC_NA_1 - Double command */
typedef struct {
    uint8_t     dco;        // Double command SE|QU(5)|DCS(2)
} asdu46;

/* C_RC_NA_1 - Regulating step command */
typedef struct {
    uint8_t     rco;        // Regulating step command SE|QU(5)|RCS(2)
} asdu47;

/* C_SE_NA_1 - Set-point Command, normalized value */
typedef struct {
    int16_t     nva;        // Normalized value
    uint8_t     qos;        // Qualifier of set-point command SE|QL(7)
} asdu48;

/* C_SE_NB_1 - Set-point Command, scaled value */
typedef struct {
    int16_t     sva;        // Scaled value
    uint8_t     qos;        // Qualifier of set-point command SE|QL(7)
} asdu49;

/* C_SE_NC_1 - Set-point Command, short floating point number */
typedef struct {
    float       r32;        // floating point value
    uint8_t     qos;        // Qualifier of set-point command SE|QL(7)
} asdu50;

/* C_BO_NA_1 - Bitstring of 32 bit command */
typedef struct {
    uint32_t    bsi;        // Binary state information
} asdu51;

/* with time tag CP56Time2a */

/* C_SC_TA_1 - Single command with time tag CP56Time2a */
typedef struct {
    uint8_t     sco;        // Single command SE|QU(5)|0|SCS
    cp56time2a	time;
} asdu58;

/* C_DC_TA_1 - Double command with time tag CP56Time2a */
typedef struct {
    uint8_t     dco;        // Double command SE|QU(5)|DCS(2)
    cp56time2a	time;
} asdu59;

/* C_RC_TA_1 - Regulating step command with time tag CP56Time2a */
typedef struct {
    uint8_t     rco;        // Regulating step command SE|QU(5)|RSC(2)
    cp56time2a	time;
} asdu60;
/* C_SE_TA_1 - Measured value, normalized value command with time tag CP56Time2a */
typedef struct {
    int16_t     nva;        // Normalized value
    uint8_t     qos;        // Qualifier of set-point command SE|QL(7)
    cp56time2a	time;
} asdu61;

/* C_SE_TB_1 - Measured value, scaled value command with time tag CP56Time2a */
typedef struct {
    int16_t     sva;        // Scaled value
    uint8_t     qos;        // Qualifier of set-point command SE|QL(7)
    cp56time2a	time;
} asdu62;

/* C_SE_TC_1 - Measured value, short floating point number command with time tag CP56Time2a */
typedef struct {
    float       r32;        // floating point value
    uint8_t     qos;        // Qualifier of set-point command SE|QL(7)
    cp56time2a	time;
} asdu63;

/* C_BO_TA_1 - Bitstring of 32 bit command with time tag CP56Time2a */
typedef struct {
    uint32_t    bsi;        // Binary state information
    cp56time2a	time;
} asdu64;

/* C_IC_NA_1 - Interrogation command */
typedef struct {
    uint8_t     qoi;    // Qualifier of interrogation command
} asdu100;

/* C_CI_NA_1 - Counter interrogation command */
typedef struct {
    uint8_t     qcc;    // Qualifier of counter interrogation FRZ(2)|RQT(6)
} asdu101;

/* C_RD_NA_1 - Read command */
typedef struct {
    uint8_t     na;
} asdu102;

/* C_CS_NA_1 - 	Clock synchronization command */
typedef struct {
    cp56time2a	time;
} asdu103;

/* C_TS_NA_1 - Test command */
typedef struct {
    uint16_t    fbp;    // =0x55AA
} asdu104;

/* C_RP_NA_1 - Reset process command */
typedef struct {
    uint8_t     qrp;    // Qualifier of reset process command
} asdu105;

/* C_TS_TA_1 - Test command with time tag CP56Time2a */
typedef struct {
    uint16_t    tsc;    // Test counter
    cp56time2a	time;
} asdu107;

/* P_ME_NA_1 - Parameter of measured value, normalized value */
typedef struct {
    uint16_t    mv;     // Normalized value
    uint8_t     qpm;    // Qualifier of parameter of measured value LPC|POP|KPA(6)
} asdu110;

/* P_ME_NB_1 - Parameter of measured values, scaled value */
typedef struct {
    uint16_t    mv;     // Scaled value
    uint8_t     qpm;    // Qualifier of parameter of measured value LPC|POP|KPA(6)
} asdu111;

/* P_ME_NC_1 - Parameter of measured values, short floating point number */
typedef struct {
    float       mv;     // Short floating point value
    uint8_t     qpm;    // Qualifier of parameter of measured value LPC|POP|KPA(6)
} asdu112;

/* P_AC_NA_1 - Parameter activation */
typedef struct {
    uint8_t     qpa;    // Qualifier of parameter activation
} asdu113;

/* M_ST_NA_1 - Step position information */
typedef struct {
    uint8_t     vti;    // Value with transient state indication (bit 7)
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|0|0|0|OV
} asdu5;

/* M_ST_TB_1 - Step position information with time tag CP56Time2a */
typedef struct {
    uint8_t     vti;    // Value with transient state indication
    uint8_t     qds;    // quality descriptor IV|NT|SB|BL|0|0|0|OV
    cp56time2a	time;
} asdu32;

/* M_IT_NA_1 - Integrated total */
typedef struct {
    uint32_t    bcr;    // Binary counter reading
    uint8_t     qds;    // quality descriptor IV|CA|CY|SQN(5)
} asdu15;

/* M_IT_TB_1 - Integrated total with time tag CP56Time2a */
typedef struct {
    uint32_t    bcr;    // Binary counter reading
    uint8_t     qds;    // quality descriptor IV|CA|CY|SQN(5)
    cp56time2a	time;
} asdu37;

typedef struct {
    uint8_t t0;
    uint8_t t1;
    uint8_t t2;
    uint8_t t3;    
    uint8_t k;
    uint8_t w;
    uint8_t oa;
    uint8_t ca_len;
    uint8_t ioa_len;
} iec_settings_t;

typedef union {
    float       real;
    int32_t     int32;
    uint32_t    uint32;
    int16_t     int16;
    uint16_t    uint16;
    int8_t      int8;
    uint8_t     uint8;
} iec_variant_t;

typedef struct {
    uint8_t         type;
    uint8_t         qds;
    struct timeval  tv;
    iec_variant_t   value;
    void*           userdata;
} info_object_t;

typedef struct {
    uint16_t flags;
    uint16_t port;
    char address[INET6_ADDRSTRLEN];
    uint64_t received;
    uint64_t transmitted;
} iec_socket_info_t;

#pragma pack(pop)

typedef struct {
    int     count;
    int     max;
    int     ca;
} sector_t;

typedef struct {
    int     flags;
    int     h_socket;
    char    ip[INET6_ADDRSTRLEN];
    int     port;
    int     count;
    char* allowed;
    iec_settings_t  is;
    uint32_t sectors[IEC_MAX_SECTORS / 32];
} socket_t;

/*
*===============================================================================================================
*= = 类型定义
*===============================================================================================================
*/

typedef void (*iec_object_listener_t)(const uint16_t ca, const uint32_t ioa, const info_object_t* info);
typedef void (*iec_status_listener_t)(const uint16_t ca, const int status);
typedef void (*iec_event_listener_t)(const char* msg);
typedef int (*iec_command_func_t)(const uint16_t ca, uint32_t ioa, iec_variant_t* value);
typedef void (*iec_timer_func_t)(time_t t);

/*
*===============================================================================================================
*= = 函数定义
*===============================================================================================================
*/

/*
int iec_sector_max_num(uint8_t type, uint8_t sq);

void time_t_to_cp56time2a(cp56time2a* tm, time_t* t);
time_t cp56time2a_to_time_t(cp56time2a* tm);
void cp56time2a_to_tm(cp56time2a* tm, struct tm* tml);
void cp56time2a_to_tv(cp56time2a* tm, struct timeval* tv);
void tv_to_cp56time2a(cp56time2a* tm, struct timeval* tv);
*/

int iec_init(int sector_max, int socket_max, iec_settings_t* is, syncobj_t* syncobj);
void iec_free();
int iec_start();
void iec_stop();
int iec_running();
int iec_lock();
int iec_unlock();
void iec_wait();

void iec_set_object_listener(iec_object_listener_t listener);
void iec_set_status_listener(iec_status_listener_t listener);
void iec_set_event_listener(iec_event_listener_t listener);

void iec_set_command_func(iec_command_func_t func);
void iec_set_timer_func(iec_timer_func_t func);

const char* iec_lasterror();
const char* iec_strerror(int errcode);

//syncobj_t* iec_get_syncobj();
int iec_get_sockets_count();
int iec_get_sectors_count();
int iec_get_objects_count(uint32_t ca);
int iec_get_sectors_list(int index, uint16_t** result);
int iec_get_objects_list(uint32_t ca, uint32_t** result);
int iec_get_socket_info(int index, iec_socket_info_t* result);

int iec_sector_new(const int ca, const int max_count, const int max_ioa);
int iec_sector_add_info(const int ca, uint32_t ioa, uint8_t type, uint8_t flags);
int iec_sector_add_cmd(const int ca, uint32_t ioa, uint8_t flags, const int l_ca, uint32_t l_ioa);
int iec_object_duplicate(const int ca, uint32_t ioa, const int l_ca, uint32_t l_ioa);
int iec_object_set_value(const int ca, uint32_t ioa, void* value, uint16_t* qds, struct timeval* tv);
int iec_object_send_cmd(const int ca, uint32_t ioa, iec_variant_t* cmd);
int iec_object_get_info(const int ca, uint32_t ioa, info_object_t* info);
void* iec_object_get_userdata(const int ca, uint32_t ioa);
void iec_object_set_userdata(const int ca, uint32_t ioa, void* userdata);
int iec_sector_status(const int ca);

int iec_socket_new(const char* addr, const int port, const int count, const int flags, iec_settings_t* is);
int iec_socket_add_sector(const int index, const int ca);
int iec_socket_status(const int index);
int iec_socket_set_allowed_list(const int index, const char* addr_list);

int iec_save_data(const char* filename);
int iec_load_data(const char* filename);

int iec_set_status_sector(const int ca);

int iec_load_config_from_files(const char* path, const char* sockets_file,
    const char** data_files, const iec_settings_t* is, syncobj_t* syncobj);
int iec_load_config_from_mem(const char* sockets_buf, const char** data_bufs,
    const iec_settings_t* is, syncobj_t* syncobj);


#ifdef  __cplusplus
}
#endif // End of __cplusplus

#endif // End of __ORCINUS_H__


/*
****************************************************************************************************************
*= = 文件结束
****************************************************************************************************************
*/


